home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 7248 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  6.3 KB

  1. Path: pegasus.montclair.edu!harmon
  2. From: harmon@pegasus.montclair.edu (Derek Harmon)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: RETURN ();
  5. Date: 8 Feb 1996 20:31:47 -0500
  6. Organization: Montclair State University
  7. Message-ID: <harmon.823829370@pegasus.montclair.edu>
  8. References: <DMFxxq.7M7@emi.net>
  9. NNTP-Posting-Host: pegasus.montclair.edu
  10. X-Newsreader: NN version 6.5.0 #68 (NOV)
  11.  
  12. ** Quoting a message by <samstar@emi.net> dated <08-Feb-1996>:
  13.  
  14. > Is there a way to return muliple values to main from a seperate function ?
  15.  
  16.   Yes, but it won't be as straightforward as this:
  17.  
  18. > return(x,y,z);
  19.  
  20.   Ready?  :>  Let's start with a little background,
  21.  
  22.   If you declare a function as returning an int ...
  23. ... C expects return() with an expression evaluating to an int
  24. (of course, that could be as simple as an int value or variable).
  25.  
  26.   The caller will receive that int if it is using the function as
  27. an part of an expression or assignment:
  28.  
  29. : val_returned = func(x,y,z);
  30. : if ((val_returned = func(x,y,z+1)) != 0) { ...
  31.  
  32.   By using a simple type like int, however, you are limited to returning
  33. only one element of data.  Unfortunately, C places limitations on the
  34. return of complex data types, but there are ways around this.
  35.  
  36.   Alternatives,
  37.  
  38. : long int func(short int a, short int b, short int c)
  39. : {
  40. :    long int temp;
  41. :
  42. :    temp = max(a,b);
  43. :    temp |= max(a,c) << 8;
  44. :    temp |= max(b,c) << 16;
  45. :
  46. :    return( temp );
  47. : }
  48.  
  49.   In this first example, which takes 3 bytes, compares all combinations
  50. determining the maximum of each, and then returns the 3 results of the
  51. these comparisons by masking the result into successively higher bytes
  52. of a long integer (usually 4-bytes).  In effect, this function returns
  53. the max(a,b), max(a,c), and max(b,c).  It has the drawback of requiring
  54. the caller to "unstuff" the returned long value.
  55.  
  56.   Many times we create structures and arrays in C, and are limited by
  57. the restrictions of C function parameters and return types.  However,
  58. one of the most versatile, and often most complicated to the novice,
  59. data types is a simple type -- the pointer.
  60.  
  61.   So, if it is possible to return a pointer to a more complex data type,
  62. its not too difficult to reference it outside of the function.  Here is
  63. an example in which the function reserves its own data space (note that
  64. it must be declared static, such that the data persists after the function
  65. concludes) as an array with enough elements to represent all of its return
  66. values.
  67.  
  68. : float *func(float x0, float x, float y0, float y, float z0, float z)
  69. : {
  70. :    static float delta[3];
  71. :
  72. :    delta[0] = x0 - x;
  73. :    delta[1] = y0 - y;
  74. :    delta[2] = z0 - z;
  75. :
  76. :    return( delta );
  77. : }
  78.  
  79.   This function returns a pointer to a float (real number).  We are depending
  80. here upon an array reserved within func() to serve as the location for the
  81. values calculated by that function.  We also rely upon delta, the name of an
  82. array, sans square brackets (delta[1] would be a float), to devolve into a
  83. pointer to the first element of delta (that would be delta[0]), when it
  84. is returned.  Remember, this function is declared as a function returning
  85. a pointer to an float.. therefore return() must be given an expression
  86. that ends up as a pointer to an float.
  87.  
  88.   The benefits of this are that the parent program can access the multiple
  89. ints resulting from the processing of func(), as follows:
  90.  
  91. : /* in another piece of code, in some function far, far away */
  92. : float *p;
  93. : float dx, dy, dz;
  94. :
  95. : p = func(17.0, 17.014, -5.5, -4.99734, 2.25, 2.252);
  96.  
  97.   Then displayed as:
  98.  
  99. : dx = p[0];
  100. : dy = p[1];
  101. : dz = p[2];
  102. : printf("dx= %f, dy= %f, dz= %f", dx, dy, dz);
  103.  
  104.   Here the square brackets have been applied to the pointer, in effect,
  105. treating it as an array of floats.  In this case, it is safe to do so
  106. because we know that there are 3 valid elements (held in the statically
  107. maintained delta[], in func() ).  It is equivalent to using pointer
  108. arithmetic, and you may be more comfortable doing the following:
  109.  
  110. : char v;
  111. :
  112. : v = 'x'
  113. : while (v <= 'z') {
  114. :   printf("d%c= %f, ", v, *p);
  115. :   p++;
  116. : }
  117.  
  118.   Maybe not everyone is comfortable with using chars as loop control
  119. variables, but that was only convenient to make the output identical
  120. to the last snippet.  If you are only displaying, it doesn't matter
  121. if you lose the pointer's place, you can always back-up! :)  The data
  122. is elsewhere.
  123.  
  124.   But there is a MAJOR caveat to go along with this seemingly more
  125. feasible solution to your troubles; be careful about your boundaries.
  126. Think of the havoc that could be wrought if we referenced p[7].  The
  127. static array only had 3 elements, not eight.  p[7] is an address out
  128. in never-never land (20 bytes, or 5 * sizeof(float) past the end of
  129. the array)!
  130.  
  131.   In the example, it was clear that there were 3 variables, x, y, and
  132. z.  If you were printing the answers, its difficult for you to come up
  133. with a letter after z and accidentally reference p[3]. :)  But that is
  134. where pointers will get you if you don't use them with care.  The
  135. approach of using an array to return multiple values from a function
  136. rests upon the assumption that the other functions have knowledge of
  137. how many values are to be returned (admittedly, bad design dogma).
  138.  
  139.   For a final illustration, I will suggest a protocol that would hopefully
  140. prevent this.  Instead of knowing, func() returns 3 values, all outside
  141. functions need to be aware of is that func() returns a pointer to the
  142. first value of an answer, many more may follow in sequence, but they will
  143. be terminated by some arbitrary value not in the solution set (we will take
  144. this to be zero).  This func() takes a number n, and returns a pointer to n,
  145. followed by the n - 1 numbers less than n, ending conveniently enough at 0.  :)
  146.  
  147. : int *func(int n)
  148. : {
  149. :   int *head;
  150. :   int *pt;
  151. :
  152. :   if ((head = pt = (int *)malloc( (n + 1) * sizeof(int) )) == NULL) {
  153. :     fputs( "Out of memory.\n", stderr);
  154. :     exit( 1 );
  155. :   }
  156. :   while (n >= 0) {
  157. :     *pt = n;
  158. :     pt++;
  159. :     n--;
  160. :   }
  161. :
  162. :   return( head );
  163. : }
  164.  
  165.   I hope some of these examples can be of help to you.
  166.  
  167.                                                                 -- Stone
  168. --
  169. [ SSS TTT OOO N  N EEE ] Derek Harmon (a.k.a. Stonelight)
  170. [ S_   T  O O NN N E_  ] E-Mail: harmon@pegasus.montclair.edu
  171. [   S  T  O O N NN E   ] Computer Science Undergrad at
  172. [ SSS  T  OOO N  N EEE ] Montclair State University, NJ
  173. (My views are entirely my own, nobody else is this creative :)
  174.  
  175.  
  176.